﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace kangsuce.DAL
{
    public class GenericRepository<T> where T : class, new()
    {
        internal MyContext context;
        internal DbSet<T> dbSet;

        public GenericRepository(MyContext context)
        {
            this.context = context;
            this.dbSet = context.Set<T>();
        }


        /// <summary>
        /// 根据Id获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public T GetModelByID(object id)
        {
            return dbSet.Find(id);
        }

        /// <summary>
        /// 根据条件获取实体
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public T GetModel(Expression<Func<T, bool>> filter)
        {
            return dbSet.FirstOrDefault(filter);
        }

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="entity"></param>
        public void Insert(T entity)
        {
            dbSet.Add(entity);
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="list"></param>
        public void Insert(List<T> list)
        {
            dbSet.AddRange(list);
        }


        /// <summary>
        /// 根据id删除实体
        /// </summary>
        /// <param name="id"></param>
        public void Delete(object id)
        {
            T entity = dbSet.Find(id);
            Delete(entity);
        }

        /// <summary>
        /// 删除实体
        /// </summary>
        /// <param name="entity"></param>
        public virtual void Delete(T entity)
        {
            if (context.Entry(entity).State == EntityState.Detached)
            {
                dbSet.Attach(entity);
            }
            dbSet.Remove(entity);
        }

        /// <summary>
        /// 根据条件批量删除实体
        /// </summary>
        /// <param name="filter"></param>
        public void DeleteByFilter(Expression<Func<T, bool>> filter)
        {
            var list = dbSet.Where(filter).AsEnumerable();
            dbSet.RemoveRange(list);
        }

        /// <summary>
        /// 删除所有实体
        /// </summary>
        public void DeleteAll()
        {
            var list = dbSet.AsEnumerable();
            dbSet.RemoveRange(list);
        }

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="entity"></param>
        public void Update(T entity)
        {
            dbSet.Attach(entity);
            context.Entry(entity).State = EntityState.Modified;
        }

        /// <summary>
        /// 获取实体列表
        /// </summary>
        /// <param name="filter">查询条件lamda表达式  实例：c => true</param>
        /// <param name="isEdit">是否用于编辑</param>
        /// <param name="orderBy">排序 实例：c=>c.OrderBy(p=>p.Name)</param>
        /// <returns></returns>
        public List<T> GetList(Expression<Func<T, bool>> filter, bool isEdit = false, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null)
        {
            IQueryable<T> query = dbSet;
            if (orderBy != null)
            {
                query = orderBy(query);
            }
            return isEdit ? query.Where(filter).AsQueryable().ToList() : query.Where(filter).AsQueryable().AsNoTracking().ToList();
        }

        /// <summary>
        /// 分页获取实体列表
        /// </summary>
        /// <param name="pageSize">页面大小</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="total">返回总数</param>
        /// <param name="filter">查询条件lamda表达式  实例：c => true</param>
        /// <param name="orderBy">排序 实例：c=>c.OrderBy(p=>p.Name)</param>
        /// <param name="isEdit">是否用于编辑</param>
        /// <returns></returns>
        public List<T> GetListByPage(int pageSize, int pageIndex, out int total, Expression<Func<T, bool>> filter = null,
            Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, bool isEdit = false)
        {
            IQueryable<T> query = dbSet;
            if (filter != null)
            {
                query = query.Where(filter);
            }
            total = query.Count();
            if (orderBy != null)
            {
                query = orderBy(query);
            }
            query = query.Skip(pageSize*(pageIndex - 1)).Take(pageSize);
            if (isEdit)
            {
                return query.ToList();
            }
            return query.AsNoTracking().ToList();
        }

        /// <summary>
        /// 分页获取实体列表
        /// </summary>
        /// <param name="pageSize">页面大小</param>
        /// <param name="pageIndex">页码</param>
        /// <param name="total">返回总数</param>
        /// <param name="sqlWhere"></param>
        /// <param name="filter">查询条件lamda表达式  实例：c => true</param>
        /// <param name="orderBy">排序 实例：c=>c.OrderBy(p=>p.Name)</param>
        /// <param name="isEdit">是否用于编辑</param>
        /// <returns></returns>
        public List<T> GetListByPageForSql(int pageSize, int pageIndex, out int total, string sqlWhere = "",
            Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
            bool isEdit = false)
        {
            var l = context.Database.SqlQuery<T>(sqlWhere);
            IQueryable<T> query = dbSet.SqlQuery(sqlWhere).AsQueryable();
            if (filter != null)
            {
                query = query.Where(filter);
            }
            total = query.Count();
            if (orderBy != null)
            {
                query = orderBy(query);
            }
            query = query.Skip(pageSize*(pageIndex - 1)).Take(pageSize);
            if (isEdit)
            {
                return query.ToList();
            }
            return query.AsNoTracking().ToList();
        }
    }
}